using CommunityToolkit.Mvvm.Messaging;
using ImageCSharp.Core.Events;
using ImageCSharp.Core.Interfaces;
using ImageCSharp.Core.Models;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System.IO;

namespace ImageCSharp.Core.Services
{
    /// <summary>
    /// 图像服务实现
    /// </summary>
    public class ImageService : IImageService
    {
        public void SaveImage(ImageDocument document, string filePath)
        {
            if (document?.Image == null)
                throw new ArgumentNullException(nameof(document));

            var extension = Path.GetExtension(filePath).ToLower();
            IImageEncoder encoder = extension switch
            {
                ".jpg" or ".jpeg" => new JpegEncoder { Quality = 90 },
                ".png" => new PngEncoder(),
                _ => new PngEncoder()
            };

            document.Image.Save(filePath, encoder);
        }

        public ImageDocument LoadImage(string filePath)
        {
            if (!File.Exists(filePath))
                throw new FileNotFoundException($"Image file not found: {filePath}");

            var image = Image.Load<Rgba32>(filePath);
            var document = new ImageDocument(filePath)
            {
                Image = image
            };

            return document;
        }

        public void ResizeImage(ImageDocument document, int width, int height)
        {
            if (document?.Image == null)
                return;

            document.Image.Mutate(x => x.Resize(width, height));
            document.IsModified = true;
        }

        public void CropImage(ImageDocument document, System.Drawing.Rectangle cropArea)
        {
            if (document?.Image == null)
                return;

            document.Image.Mutate(x => x.Crop(new Rectangle(
                cropArea.X, cropArea.Y, cropArea.Width, cropArea.Height)));
            document.IsModified = true;
        }

        public void RotateImage(ImageDocument document, float angle)
        {
            if (document?.Image == null)
                return;

            document.Image.Mutate(x => x.Rotate(angle));
            document.IsModified = true;
        }

        public void FlipImage(ImageDocument document, bool horizontal, bool vertical)
        {
            if (document?.Image == null)
                return;

            if (horizontal)
                document.Image.Mutate(x => x.Flip(FlipMode.Horizontal));
            
            if (vertical)
                document.Image.Mutate(x => x.Flip(FlipMode.Vertical));

            document.IsModified = true;
        }

        public void ApplyFilter(ImageDocument document, IFilterPlugin filter)
        {
            if (document?.Image == null)
                return;

            //// 如果有选择区域，只对选择区域应用滤镜
            //if (document.SelectionArea.Width > 0 && document.SelectionArea.Height > 0)
            //{
            //    ApplyFilterToSelection(document, filter);
            //}
            //else
            //{
            //    // 对整个图像应用滤镜
            //    var processedImage = filter.ProcessImage(document.Image);
            //    //document.Image = processedImage.Clone();
            //    document.Image = processedImage.CloneAs<Rgba32>();
            //}

            // 对整个图像应用滤镜
            var processedImage = filter.ProcessImage(document.Image);
            //document.Image = processedImage.Clone();
            document.Image = processedImage.CloneAs<Rgba32>();

            // 触发文档变更事件
            WeakReferenceMessenger.Default.Send(new ImageDocumentChangedEvent(document));

            document.IsModified = true;
        }

        public ImageDocument ApplyFilter2(ImageDocument document, IFilterPlugin filter)
        {
            if (document?.Image == null)
                return document;

            ImageDocument oldDocument = document.Clone();

            // 如果有选择区域，只对选择区域应用滤镜
            if (document.SelectionArea.Width > 0 && document.SelectionArea.Height > 0)
            {
                var processedImage = ApplyFilterToSelection(oldDocument, filter);
                oldDocument.Image = processedImage.CloneAs<Rgba32>();
            }
            else
            {
                // 对整个图像应用滤镜
                var processedImage = filter.ProcessImage(oldDocument.Image);
                oldDocument.Image = processedImage.CloneAs<Rgba32>();
            }

            document = oldDocument;
            document.IsModified = true;

            return document;
        }


        private Image ApplyFilterToSelection(ImageDocument document, IFilterPlugin filter)
        {
            var selection = document.SelectionArea;
            
            // 克隆原始图像
            var result = document.Image.Clone();
            
            // 确保选择区域在图像范围内
            var selectionRect = new Rectangle(
                Math.Max(0, (int)selection.X),
                Math.Max(0, (int)selection.Y),
                Math.Min((int)selection.Width, document.Image.Width - (int)selection.X),
                Math.Min((int)selection.Height, document.Image.Height - (int)selection.Y)
            );

            // 只对选择区域应用滤镜
            result.Mutate(x => 
            {
                // 裁剪选择区域
                var cropped = result.Clone(ctx => ctx.Crop(selectionRect));
                
                // 对裁剪的图像应用滤镜
                var filtered = filter.ProcessImage(cropped);

                result.Mutate(ctx => // 核心修正：lambda参数名改为ctx，与内部调用一致
                {
                    // 将处理后的选择区域绘制回原位置（透明度1.0f）
                    ctx.DrawImage(filtered, new Point(selectionRect.X, selectionRect.Y), 1.0f);
                });

            });
            
            document.Image = result;

            return document.Image;
        }
		
        public ImageStatistics GetStatistics(ImageDocument document)
        {
            if (document?.Image == null)
                throw new ArgumentNullException(nameof(document));

            var stats = new ImageStatistics
            {
                Width = document.Image.Width,
                Height = document.Image.Height
            };

            // 计算基本统计信息
            double totalBrightness = 0;
            double totalR = 0, totalG = 0, totalB = 0;
            double maxBrightness = 0, minBrightness = 255;
            var colorCounts = new Dictionary<string, int>();
            var brightnessHistogram = new int[256];
            
            for (int y = 0; y < document.Image.Height; y++)
            {
                for (int x = 0; x < document.Image.Width; x++)
                {
                    var pixel = document.Image[x, y];
                    
                    // 计算亮度
                    var brightness = (pixel.R + pixel.G + pixel.B) / 3.0;
                    totalBrightness += brightness;
                    
                    // 计算RGB平均值
                    totalR += pixel.R;
                    totalG += pixel.G;
                    totalB += pixel.B;
                    
                    // 亮度直方图
                    brightnessHistogram[(int)brightness]++;
                    
                    // 最大最小亮度
                    maxBrightness = Math.Max(maxBrightness, brightness);
                    minBrightness = Math.Min(minBrightness, brightness);

                    // 简化的颜色分布统计
                    var colorKey = GetColorRange(pixel);
                    if (!colorCounts.ContainsKey(colorKey))
                        colorCounts[colorKey] = 0;
                    colorCounts[colorKey]++;
                }
            }

            int totalPixels = document.Image.Width * document.Image.Height;
            
            // 基本统计
            stats.MeanBrightness = totalBrightness / totalPixels / 255.0;
            stats.MeanRed = totalR / totalPixels;
            stats.MeanGreen = totalG / totalPixels;
            stats.MeanBlue = totalB / totalPixels;
            
            // 对比度
            stats.Contrast = (maxBrightness - minBrightness) / 255.0;
            
            // 熵（简化计算）
            stats.Entropy = CalculateEntropy(brightnessHistogram, totalPixels);
            
            // 标准差
            stats.StandardDeviation = CalculateStandardDeviation(document.Image, stats.MeanBrightness * 255.0);
            
            // 颜色分布百分比
            foreach (var kvp in colorCounts)
            {
                stats.ColorDistribution[kvp.Key] = (double)kvp.Value / totalPixels * 100;
            }

            return stats;
        }

        private double CalculateEntropy(int[] histogram, int totalPixels)
        {
            double entropy = 0;
            for (int i = 0; i < histogram.Length; i++)
            {
                if (histogram[i] > 0)
                {
                    double probability = (double)histogram[i] / totalPixels;
                    entropy -= probability * Math.Log2(probability);
                }
            }
            return entropy;
        }

        private double CalculateStandardDeviation(Image<Rgba32> image, double mean)
        {
            double sumSquaredDiff = 0;
            int totalPixels = image.Width * image.Height;
            
            for (int y = 0; y < image.Height; y++)
            {
                for (int x = 0; x < image.Width; x++)
                {
                    var pixel = image[x, y];
                    var brightness = (pixel.R + pixel.G + pixel.B) / 3.0;
                    sumSquaredDiff += Math.Pow(brightness - mean, 2);
                }
            }
            
            return Math.Sqrt(sumSquaredDiff / totalPixels);
        }

        private string GetColorRange(Rgba32 pixel)
        {
            // 简化的颜色分类
            if (pixel.R > 200 && pixel.G < 100 && pixel.B < 100) return "Red";
            if (pixel.R < 100 && pixel.G > 200 && pixel.B < 100) return "Green";
            if (pixel.R < 100 && pixel.G < 100 && pixel.B > 200) return "Blue";
            if (pixel.R > 200 && pixel.G > 200 && pixel.B > 200) return "White";
            if (pixel.R < 50 && pixel.G < 50 && pixel.B < 50) return "Black";
            return "Other";
        }
    }
}